/**
 * 
 */
package ai.human

import ai.AIEngine
import data.Player
import data.Data.PlayerState
import data.Data.Role

/**
 * Players group.
 * 
 * @author Tomasz Dąbrowski
 *
 */
class PlayerGroup {

	/**
	 * AI engine.
	 */
	final AIEngine aiEngine
	/**
	 * Group id.
	 */
	int id;
	/**
	 * Main player.
	 */
	Player mainPlayer;
	/**
	 * Temporary main player.
	 */
	Player temporaryMainPlayer;
	/**
	 * Support players.
	 */
	final List<Player> supportPlayers = []

	/**
	 * Calculates the player power.
	 */
	static def playerPower = { Player p ->
		switch (p.role()) {
			case [Role.CATCHER, Role.THROWER]:
				10
				break
			case [Role.BLITZER, Role.BLOCKER]:
				4
				break
			case Role.LINEMAN:
				3
				break
			default:
				assert false
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Group of leader: ${getMainPlayer()}"
	}

	/**
	 * Adds a support player.
	 *
	 * @param player
	 *
	 * @author Tomasz Dąbrowski
	 */
	public void addSupportPlayer(Player player) {
		supportPlayers << player
		player.playerGroup = this
	}

	/**
	 * Updates the main player.
	 *
	 * @author Tomasz Dąbrowski
	 */
	public void updateMainPlayer() {
		if (temporaryMainPlayer) {
			supportPlayers.remove(mainPlayer)
			supportPlayers.add(temporaryMainPlayer)
			temporaryMainPlayer = null
		}
		temporaryMainPlayer = supportPlayers.find { it.hasBall() && it.state() == PlayerState.IN_PLAY }
		if(temporaryMainPlayer) {
			supportPlayers.remove(temporaryMainPlayer)
			supportPlayers.add(mainPlayer)
		}
		if(mainPlayer.state() != PlayerState.IN_PLAY) {
			def support = supportPlayers.collect {(it.state() == PlayerState.IN_PLAY) ? it : null }.findAll().sort { playerPower(it) }
			temporaryMainPlayer = support ? support.last() : null
			if(temporaryMainPlayer) {
				supportPlayers.remove(temporaryMainPlayer)
				supportPlayers.add(mainPlayer)
			}
		}
	}

	/**
	 * Gets a temporary or the main player.
	 *
	 * @return main player
	 *
	 * @author Tomasz Dąbrowski
	 */
	public Player getMainPlayer() {
		temporaryMainPlayer ?: mainPlayer;
	}

	/**
	 * Sets the main player.
	 *
	 * @param mainPlayer main player
	 *
	 * @author Tomasz Dąbrowski
	 */
	public void setMainPlayer(Player mainPlayer) {
		this.mainPlayer = mainPlayer;
		this.temporaryMainPlayer = null;
		mainPlayer.setPlayerGroup(this);
	}

	/**
	 * Gets all players.
	 *
	 * @return all players
	 *
	 * @author Tomasz Dąbrowski
	 */
	public List<Player> getPlayers() {
		players.collect() << getMainPlayer()
	}

	/**
	 * Gets an overall power of support players.
	 *
	 * @return support power
	 */
	public int getSupportPower() {
		supportPlayers.sum { Player p ->
			assert p.role() in [
				Role.BLITZER,
				Role.BLOCKER,
				Role.LINEMAN
			]
			PlayerGroup.playerPower(p)
		} ?: 0
	}

	/**
	 * Checks if from group.
	 *
	 * @param player player
	 * @return is gr
	 *
	 * @author Tomasz Dąbrowski
	 */
	public boolean isFromGroup(Player player) {
		getMainPlayer() == player ?: player in supportPlayers
	}
}
